import uuid
from django.db import models
from pgcrypto import fields

from apps.core.models import GenericModel
from apps.core.types import DAY_OF_WEEK_CHOICES, INVOICE_STATUS_CHOICES
from apps.users.models import (
    User, Provider
)
from .types import (
    RoomPermission,
    ROOM_PERMISSION,
)
from ..billing.types import InvoiceStatus
from ..booking.types import BookingStatusChoices, BOOKING_STATUS_CHOICES
from django.conf import settings


# Create your models here.

def increment_room_order(location):
    # Get the total number of rooms for the current room's location
    total_rooms = Room.objects.filter(location=location).count()

    # Increment the order number by 1
    incremented_order = total_rooms + 1

    return incremented_order


def location_image_path(instance, filename):
    if instance:
        return f"{settings.GS_BUCKET_NAME}/Location_image/{instance.id}/{filename}"

def upload_location_map(instance, filename):
    if instance:
        return f"{settings.GS_BUCKET_NAME}/location_map/{instance.id}/{filename}"


class Location(GenericModel):
    id = models.UUIDField(primary_key=True, default=uuid.uuid4)
    name = models.CharField(max_length=255, blank=False)
    image = models.ImageField(upload_to=location_image_path, null=True, blank=True)
    contact_person = models.CharField(max_length=255, blank=True)
    email = models.EmailField()
    address = models.CharField(max_length=255)
    phone_number = models.CharField(blank=True, max_length=20)
    room_map = models.FileField(upload_to=upload_location_map, null=True, blank=True)
    room_map_mapping = models.TextField(default="[]")

    class Meta:
        db_table = 'locations'
        ordering = ['name']


class OperatingHourLocation(models.Model):
    location = models.ForeignKey(Location,
                                 on_delete=models.CASCADE,
                                 related_name='operating_hours')
    day_of_week = models.IntegerField(choices=DAY_OF_WEEK_CHOICES)
    start_time = models.TimeField()
    close_time = models.TimeField()
    is_useable = models.BooleanField(default=False)

    class Meta:
        db_table = 'operation_hour_locations'
        unique_together = ['location', 'day_of_week']


class LocationClosedDate(models.Model):
    location = models.ForeignKey(Location,
                                 on_delete=models.CASCADE,
                                 related_name='closed_dates')
    date = models.DateTimeField()

    class Meta:
        db_table = 'location_closed_dates'


class LocationTierSetting(models.Model):
    location = models.ForeignKey(Location,
                                 on_delete=models.CASCADE,
                                 related_name='tiers')
    tier = models.CharField(max_length=255)
    start_hours = models.IntegerField()
    end_hours = models.IntegerField()

    class Meta:
        db_table = 'location_tier_settings'


class Lock(GenericModel):
    id = models.UUIDField(primary_key=True, default=uuid.uuid4)
    location = models.ForeignKey(Location,
                                 on_delete=models.CASCADE,
                                 related_name='locks')
    name = models.CharField(max_length=255, blank=False)
    token = models.TextField(blank=False, unique=True)

    class Meta:
        db_table = 'locks'


class Room(GenericModel):
    id = models.UUIDField(primary_key=True, default=uuid.uuid4)
    location = models.ForeignKey(Location,
                                 on_delete=models.CASCADE,
                                 related_name='room')
    name = models.CharField(max_length=255)
    comment = models.CharField(max_length=255, blank=False)
    tiers_excluded = models.BooleanField(default=False)
    order = models.IntegerField(default=0)

    def save(self, *args, **kwargs):
        if self.order == 0:
            self.order = increment_room_order(self.location)
        super().save(*args, **kwargs)

    class Meta:
        db_table = 'rooms'


class RoomPrice(GenericModel):
    room = models.ForeignKey(Room,
                             on_delete=models.CASCADE,
                             related_name='room_prices')
    tier = models.ForeignKey(LocationTierSetting,
                             on_delete=models.CASCADE,
                             related_name='tier_price')
    cost = models.DecimalField(max_digits=10, decimal_places=2)

    class Meta:
        db_table = 'room_prices'
        unique_together = ['room', 'tier']


class RoomOperatingHours(models.Model):
    room = models.ForeignKey(Room,
                             on_delete=models.CASCADE,
                             related_name='operating_hours')
    day_of_week = models.IntegerField(choices=DAY_OF_WEEK_CHOICES)
    start_time = models.TimeField()
    close_time = models.TimeField()
    is_useable = models.BooleanField(default=False)

    class Meta:
        db_table = 'rooms_operating_hours'
        unique_together = ['room', 'day_of_week']


class RoomClosedDate(models.Model):
    room = models.ForeignKey(Room,
                             on_delete=models.CASCADE,
                             related_name='closed_date')
    date = models.DateTimeField()

    class Meta:
        db_table = 'rooms_closed_date'


class RoomAuthorization(models.Model):
    room = models.ForeignKey(Room,
                             on_delete=models.CASCADE,
                             related_name='room_authorization')
    user = models.ForeignKey(User,
                             on_delete=models.CASCADE,
                             related_name='authorized_user')

    permission = models.CharField(choices=ROOM_PERMISSION,
                                  default=RoomPermission.AUTHORIZED.value,
                                  max_length=1)

    class Meta:
        db_table = 'room_authorization'
        unique_together = ['room', 'user']


class AdminBookingDetails(GenericModel):
    id = models.UUIDField(primary_key=True, default=uuid.uuid4)
    provider = models.ForeignKey(Provider, on_delete=models.CASCADE, related_name='booking')
    location = models.ForeignKey(Location, on_delete=models.CASCADE)
    room = models.ForeignKey(Room, on_delete=models.CASCADE, related_name='booking_room')
    start_time = models.TimeField()
    end_time = models.TimeField()
    start_date = models.DateTimeField()
    room_cost = models.DecimalField(decimal_places=2, max_digits=10, default=0)
    appointments_start_time = models.TimeField(null=True)
    appointments_end_time = models.TimeField(null=True)
    status = models.IntegerField(choices=BOOKING_STATUS_CHOICES,
                                 default=BookingStatusChoices.ACTIVE.value)

    class Meta:
        db_table = 'admin_booking_details'


class ProviderBillings(GenericModel):
    provider = models.ForeignKey(Provider, on_delete=models.CASCADE)
    invoice_number = models.CharField(max_length=500, null=True)
    status = models.IntegerField(
        choices=INVOICE_STATUS_CHOICES,
        default=InvoiceStatus.UNPAID.value
    )
    due_date = models.DateTimeField()
    total_amount = models.DecimalField(max_digits=12, decimal_places=5)

    class Meta:
        db_table = 'provider_billings'


class AdminBookingPriceDetail(models.Model):
    booking = models.ForeignKey(AdminBookingDetails,
                                on_delete=models.CASCADE,
                                related_name='prices')
    tier = models.CharField(null=True, blank=True, max_length=50)
    hours = models.DecimalField(max_digits=4, decimal_places=2)
    price = models.DecimalField(max_digits=10, decimal_places=2)

    class Meta:
        db_table = 'admin_booking_price'